package thread;

import form.DialogFX;
import form.GUI;
import java.io.IOException;
import java.net.BindException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.util.Pair;
import services.Command;
import services.Command.ClientType;
import services.Command.Include;
import services.Command.MessageType;
import services.Host;
import services.Packet;

public class DiscoveryThreadServer implements Runnable {

    DatagramSocket socket;
    int msgPort = 4444;
    int dataPort = 4445;
    boolean is = false;
	ArrayList<String> arrayMessage;
	Thread GUIThread;

    @Override
    public void run() {
        try {
            socket = new DatagramSocket(msgPort, InetAddress.getByName("0.0.0.0"));
            socket.setBroadcast(true);
          
            //   Command.clientList.add(new Host("kopia", "192.168.0.0"));
            while (true) {


                //Receive a packet
                byte[] recvBuf = new byte[15000];
                DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
                socket.receive(packet);
                if (!packet.getAddress().getHostAddress().contains(InetAddress.getLocalHost().getHostAddress())) {
                    Pair p = Packet.splitPacket(recvBuf, packet.getAddress().getCanonicalHostName());
                    String a = (String) p.getKey();
                    ArrayList<String> b = (ArrayList<String>) p.getValue();


                    for (Host h : Command.clientList) {
                        if (h.getIp().contains(packet.getAddress().getHostAddress().trim())) {
                            is = true;

                        } else {
                            is = false;
                            System.out.append(getClass().getSimpleName() + "::> Brak hosta: " + h.getName() + "\n");

                        }

                    }
                    String st = new String(recvBuf);
                    if (st.contains("CLIENT;INFO;JSON;SYNTAX")) {

                        System.out.append("Klient chce wysłać jsona bo zmienił pliki\n");
                        String msg = Packet.generatePacketAsString(ClientType.SERVER, MessageType.RESPONSE, Include.JSON, Command.ResponseCode.OK.name());
                        byte[] sendData = msg.getBytes();
                        System.out.append(getClass().getSimpleName() + "::> " + msg + "\n");
                        //Send a response
                        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
                        socket.send(sendPacket);

                        runFTPServer();
                        GUI.lf.listFile(".json");
                        GUI.refreshFlag = true;
                            System.out.append("koniec syntax\n");
                        


                    }
                     if (st.contains("CLIENT;INFO;INFO;QUIT")) {
                         Host host = null;
                         for(Host h: Command.clientList)
                         {
                             if(h.getIp().equals(packet.getAddress().getHostAddress())){
                                  host = h;
                             }
                         }
                         Command.clientList.remove(host);
                         if(Command.clientList.contains(host)){
                             System.out.println("nie usinięto skutecznie hosta");
                             
                         }
                         else System.out.println("host usunięty");
                         GUI.removeFlag = true;
                         System.out.println("RemoveFlag");
            
                  
                             
                     }
                     
                    if (st.contains("CLIENT;REQUEST;FILE;DATA")) {
                        System.out.append("Klient zada pliku!!\n");
                        System.out.println(getClass().getSimpleName() + "Serwer otrzymał: " + p.getValue());
                        String msg = Packet.generatePacketAsString(ClientType.SERVER, MessageType.RESPONSE, Include.FILE, Command.ResponseCode.OK.name());
                        byte[] sendData = msg.getBytes();
                        System.out.println("Serwer odpowiedział: " + msg);
                        //Send a response

                        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
                        socket.send(sendPacket);

                        runFTPServer();
                            System.out.append("Koniec zadania pliku przez klienta\n");
}
                    if (st.contains("CLIENT;RESPONSE;FILE;DATA")) {
                        System.out.append("Klient chce wysłać plik\n");
                        String msg = Packet.generatePacketAsString(ClientType.SERVER, MessageType.REQUEST, Include.FILE, Command.ResponseCode.OK.name());
                        byte[] sendData = msg.getBytes();
                        System.out.append(getClass().getSimpleName() + " ::> " + msg + "\n");
                        //Send a response
                        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
                        socket.send(sendPacket);

                        runFTPServer();
                            System.out.append("Koniec wysylania pliku przez klienta\n");


                    } 
                    
                    else if (!is) {
                        System.out.append("Brak takiego hosta!!\n");
                        String msg = Packet.generatePacketAsString(ClientType.SERVER, MessageType.RESPONSE, Include.INFO, Command.ResponseCode.NOINFO.name());
                        byte[] sendData = msg.getBytes();
                        System.out.append(getClass().getSimpleName() + "::> " + msg + "\n");
                        //Send a response
                        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
                        socket.send(sendPacket);

                        runFTPServer();
                        runFTPServer();
                     
                        Command.clientList.add(new Host(packet.getAddress().getCanonicalHostName(), packet.getAddress().getHostAddress()));
                        GUI.listingFlag = true;

//                        GUI.lf.listFile(".json");

                        is = true;

                    } 
                   
                    if (b.get(0).contains(Command.ClientType.CLIENT.name())) {
                        if (b.get(1).contains(Command.MessageType.INFO.name())) {
                            if (b.get(2).contains(Command.Include.JSON.toString())) {
                                if (b.get(3).contains(Command.ResponseCode.DATA.name())) {
                                    System.out.println("Serwer otrzymał:" + p.getValue());
                                    String msg = Packet.generatePacketAsString(ClientType.SERVER, MessageType.RESPONSE, Include.JSON, Command.ResponseCode.OK.name());
                                    byte[] sendData = msg.getBytes();
                                    System.out.println("Serwer odpowiedział:" + msg);
                                    //Send a response
                                    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
                                    socket.send(sendPacket);

                                    runFTPServer();
                                }
                            }
                        }


                    }
                }


            }
        } catch (IOException ex) {
            Logger.getLogger(DiscoveryThreadServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void runFTPServer() throws IOException {
        transferFileServer t;
        ServerSocket soc = null;
        try {
            soc = new ServerSocket(dataPort);

        } catch (BindException e) {
            System.out.append(getClass().getSimpleName() + "ERROR: " + e.getMessage());
            side.SideDish.wait(500);

        }

        System.out.println("Oczekiwanie na połączenie...");
        try {
            System.out.println("Start connection");
            t = new transferFileServer(soc.accept());


            if (soc.isClosed()) {
                t.interrupt();
            }
            t.interrupt();
            soc.close();
 System.out.println("End Connection");
        } catch (SocketTimeoutException e) {
            System.out.append(getClass().getSimpleName() + "ERROR: " + e.getMessage());
        }
       
        return;
    }

    public static DiscoveryThreadServer getInstance() {
        return DiscoveryThreadHolder.INSTANCE;
    }

    private static class DiscoveryThreadHolder {

        private static final DiscoveryThreadServer INSTANCE = new DiscoveryThreadServer();
    }
}
